<?php

namespace App\Models;

use App\Exceptions\ExceptionApi;
use App\Exceptions\ExceptionToken;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public static function filterData(Builder &$query, $filter=[]){
        if(isset($filter['nickname'])){
            $query->where('nickname', "like", "%{$filter['nickname']}%");
        }
        if(isset($filter['mobile'])){
            $query->where('mobile', "like", "%{$filter['mobile']}%");
        }
        if(!empty($filter['time_begin'])){
            $query->where("created_at", ">=", $filter['time_begin']);
        }
        if(!empty($filter['time_end'])){
            $query->where("created_at", "<=", $filter['time_end']);
        }
    }

    public static function findByApiToken($token){

        $tokenInfo = explode('.', $token);
        if(count($tokenInfo)!==3){
            throw new ExceptionToken('token非法');
        }
        list($vvv,$tokenHash, $userId) = $tokenInfo;
        $userModel = self::query()->find($userId);

        if(empty($userModel)){
            throw new ExceptionToken('用户不存在');
        }
        if(hash('sha256', $userModel->api_token)==$tokenHash){
            return $userModel;
        }
        throw new ExceptionToken('token错误');
    }

    public function getApiToken() :string {
        if(empty($this->api_token)){
            $this->api_token = Str::random(64);
            $this->save();
        }
        return "tkb.".hash('sha256', $this->api_token) . "." .$this->id;
    }


    public static function registerByMobile($mobile){
        $user = self::query()->where(['mobile'=>$mobile])->first();
        if($user){
            throw new ExceptionApi('用户已存在，不可注册！',500);
        }
        $user = new self();
        $user->email = $mobile."@mobile.com"; // doesn't have a default value
        //        $user->image = "";
        $user->mobile = $mobile;
        $user->api_token = Str::random(64);
        // 134*1386
        $nickname = substr($mobile, 0, 3).'*'.substr($mobile, 7);
        $user->nickname = $nickname;
        $user->name = $nickname; // doesn't have a default value
        $user->password = "123456";
        if($user->save()){
            return $user;
        }
        throw new ExceptionApi('注册失败，请重试！',500);
    }

    protected $likeVideoIdsQuery;
    protected $likeVideoQuery;
    protected $likeVideosTotal;
    protected $likeVideos;
    protected $likeIds;
    protected function getLikeVideoIdsQuery(){
        if(!$this->likeVideoIdsQuery){
            $this->likeVideoIdsQuery = LikeVideo::query()->where(['user_id'=>$this->id])->orderByDesc("updated_at");
        }
        return $this->likeVideoIdsQuery;
    }
    public function getLikeVideoIds(){
        if(!$this->likeIds){
            $likes = $this->getLikeVideoIdsQuery()->get();
            $videoIds = [];
            foreach ($likes as $like){
                $videoIds[] = $like->video_id;
            }
            $this->likeIds = $videoIds;
        }
        return $this->likeIds;
    }
    protected function getLikeVideosQuery(){
        if(!$this->likeVideoQuery){
            $videoIds = $this->getLikeVideoIds();
            $this->likeVideoQuery = Video::query()
                ->whereIn("id",$videoIds)
                ->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $videoIds) . '"' . ")"));
        }
        return $this->likeVideoQuery;
    }
    public function getLikeVideos(){
        if(!$this->likeVideos){
            $query = $this->getLikeVideosQuery();
            $this->likeVideos = $query->get();
        }
        return $this->likeVideos;
    }
    public function getLikeVideosTotal(){
        if(!$this->likeVideosTotal){
            $this->likeVideosTotal = $this->getLikeVideosQuery()->count();
        }
        return $this->likeVideosTotal;
    }
}
